// Copyright Epic Games, Inc. All Rights Reserved.


#include "LyraWeaponSpawner.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "Components/CapsuleComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/World.h"
#include "Equipment/LyraPickupDefinition.h"
#include "GameFramework/Pawn.h"
#include "Inventory/InventoryFragment_SetStats.h"
#include "Kismet/GameplayStatics.h"
#include "LyraLogChannels.h"
#include "Net/UnrealNetwork.h"
#include "NiagaraFunctionLibrary.h"
#include "NiagaraSystem.h"
#include "TimerManager.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraWeaponSpawner)

class FLifetimeProperty;
class UNiagaraSystem;
class USoundBase;
struct FHitResult;

/**
 * 设置默认值。
 */
ALyraWeaponSpawner::ALyraWeaponSpawner()
{
 	// 设置此Actor每帧调用Tick()
	PrimaryActorTick.bCanEverTick = true;

	// 创建根组件：碰撞体积
	RootComponent = CollisionVolume = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CollisionVolume"));
	CollisionVolume->InitCapsuleSize(80.f, 80.f); // 初始化胶囊体大小
	// 绑定重叠开始事件
	CollisionVolume->OnComponentBeginOverlap.AddDynamic(this, &ALyraWeaponSpawner::OnOverlapBegin);

	// 创建底座网格组件
	PadMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PadMesh"));
	PadMesh->SetupAttachment(RootComponent);

	// 创建武器网格组件
	WeaponMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMesh"));
	WeaponMesh->SetupAttachment(RootComponent);

	// 设置默认值
	WeaponMeshRotationSpeed = 40.0f; // 武器网格旋转速度
	CoolDownTime = 30.0f; // 冷却时间
	CheckExistingOverlapDelay = 0.25f; // 检查现有重叠延迟
	bIsWeaponAvailable = true; // 武器初始可用
	bReplicates = true; // 启用复制
}

/**
 * 游戏开始或生成时调用。
 */
void ALyraWeaponSpawner::BeginPlay()
{
	Super::BeginPlay();

	// 如果有武器定义，设置冷却时间
	if (WeaponDefinition && WeaponDefinition->InventoryItemDefinition)
	{
		CoolDownTime = WeaponDefinition->SpawnCoolDownSeconds;	
	}
	else if (const UWorld* World = GetWorld())
	{
		// 如果不是重放，记录错误
		if (!World->IsPlayingReplay())
		{
			UE_LOG(LogLyra, Error, TEXT("'%s' does not have a valid weapon definition! Make sure to set this data on the instance!"), *GetNameSafe(this));	
		}
	}
}

/**
 * 游戏结束时调用。
 */
void ALyraWeaponSpawner::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	// 清除所有计时器
	if (UWorld* World = GetWorld())
	{
		World->GetTimerManager().ClearTimer(CoolDownTimerHandle);
		World->GetTimerManager().ClearTimer(CheckOverlapsDelayTimerHandle);
	}
	
	Super::EndPlay(EndPlayReason);
}

/**
 * 每帧调用。
 */
void ALyraWeaponSpawner::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 更新CoolDownPercentage属性以驱动重生时间指示器
	UWorld* World = GetWorld();
	if (World->GetTimerManager().IsTimerActive(CoolDownTimerHandle))
	{
		CoolDownPercentage = 1.0f - World->GetTimerManager().GetTimerRemaining(CoolDownTimerHandle)/CoolDownTime;
	}

	// 旋转武器网格
	WeaponMesh->AddRelativeRotation(FRotator(0.0f, World->GetDeltaSeconds() * WeaponMeshRotationSpeed, 0.0f));
}

/**
 * 构建时调用。
 */
void ALyraWeaponSpawner::OnConstruction(const FTransform& Transform)
{
	// 如果有武器定义和显示网格，设置武器网格
	if (WeaponDefinition != nullptr && WeaponDefinition->DisplayMesh != nullptr)
	{
		WeaponMesh->SetStaticMesh(WeaponDefinition->DisplayMesh);
		WeaponMesh->SetRelativeLocation(WeaponDefinition->WeaponMeshOffset); // 设置相对位置
		WeaponMesh->SetRelativeScale3D(WeaponDefinition->WeaponMeshScale); // 设置相对缩放
	}	
}

/**
 * 重叠开始事件处理函数。
 */
void ALyraWeaponSpawner::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
	// 检查是否为Pawn且武器可用
	APawn* OverlappingPawn = Cast<APawn>(OtherActor);
	if (GetLocalRole() == ROLE_Authority && bIsWeaponAvailable && OverlappingPawn != nullptr)
	{
		// 尝试拾取武器
		AttemptPickUpWeapon(OverlappingPawn);
	}
}

/**
 * 检查现有重叠。
 */
void ALyraWeaponSpawner::CheckForExistingOverlaps()
{
	// 获取所有重叠的Pawn
	TArray<AActor*> OverlappingActors;
	GetOverlappingActors(OverlappingActors, APawn::StaticClass());

	// 为每个重叠的Pawn尝试拾取武器
	for (AActor* OverlappingActor : OverlappingActors)
	{
		AttemptPickUpWeapon(Cast<APawn>(OverlappingActor));
	}
}

/**
 * 尝试拾取武器实现。
 */
void ALyraWeaponSpawner::AttemptPickUpWeapon_Implementation(APawn* Pawn)
{
	// 检查是否在服务器端、武器可用且Pawn有技能系统组件
	if (GetLocalRole() == ROLE_Authority && bIsWeaponAvailable && UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Pawn))
	{
		// 获取武器物品定义
		TSubclassOf<ULyraInventoryItemDefinition> WeaponItemDefinition = WeaponDefinition ? WeaponDefinition->InventoryItemDefinition : nullptr;
		if (WeaponItemDefinition != nullptr)
		{
			// 尝试给予武器
			if (GiveWeapon(WeaponItemDefinition, Pawn))
			{
				// 武器被Pawn拾取
				bIsWeaponAvailable = false;
				SetWeaponPickupVisibility(false); // 隐藏武器拾取
				PlayPickupEffects(); // 播放拾取特效
				StartCoolDown(); // 开始冷却
			}
		}		
	}
}

/**
 * 开始冷却。
 */
void ALyraWeaponSpawner::StartCoolDown()
{
	// 设置冷却计时器
	if (UWorld* World = GetWorld())
	{
		World->GetTimerManager().SetTimer(CoolDownTimerHandle, this, &ALyraWeaponSpawner::OnCoolDownTimerComplete, CoolDownTime);
	}
}

/**
 * 重置冷却。
 */
void ALyraWeaponSpawner::ResetCoolDown()
{
	UWorld* World = GetWorld();

	// 清除冷却计时器
	if (World)
	{
		World->GetTimerManager().ClearTimer(CoolDownTimerHandle);
	}

	// 在服务器端设置武器可用并播放重生特效
	if (GetLocalRole() == ROLE_Authority)
	{
		bIsWeaponAvailable = true;
		PlayRespawnEffects(); // 播放重生特效
		SetWeaponPickupVisibility(true); // 显示武器拾取

		// 设置延迟检查现有重叠
		if (World)
		{
			World->GetTimerManager().SetTimer(CheckOverlapsDelayTimerHandle, this, &ALyraWeaponSpawner::CheckForExistingOverlaps, CheckExistingOverlapDelay);
		}
	}

	// 重置冷却百分比
	CoolDownPercentage = 0.0f;
}

/**
 * 冷却计时器完成回调。
 */
void ALyraWeaponSpawner::OnCoolDownTimerComplete()
{
	ResetCoolDown();
}

/**
 * 设置武器拾取可见性。
 */
void ALyraWeaponSpawner::SetWeaponPickupVisibility(bool bShouldBeVisible)
{
	WeaponMesh->SetVisibility(bShouldBeVisible, true);
}

/**
 * 播放拾取特效实现。
 */
void ALyraWeaponSpawner::PlayPickupEffects_Implementation()
{
	if (WeaponDefinition != nullptr)
	{
		// 播放拾取音效
		USoundBase* PickupSound = WeaponDefinition->PickedUpSound;
		if (PickupSound != nullptr)
		{
			UGameplayStatics::PlaySoundAtLocation(this, PickupSound, GetActorLocation());
		}

		// 播放拾取特效
		UNiagaraSystem* PickupEffect = WeaponDefinition->PickedUpEffect;
		if (PickupEffect != nullptr)
		{
			UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, PickupEffect, WeaponMesh->GetComponentLocation());
		}
	}
}

/**
 * 播放重生特效实现。
 */
void ALyraWeaponSpawner::PlayRespawnEffects_Implementation()
{
	if (WeaponDefinition != nullptr)
	{
		// 播放重生音效
		USoundBase* RespawnSound = WeaponDefinition->RespawnedSound;
		if (RespawnSound != nullptr)
		{
			UGameplayStatics::PlaySoundAtLocation(this, RespawnSound, GetActorLocation());
		}

		// 播放重生特效
		UNiagaraSystem* RespawnEffect = WeaponDefinition->RespawnedEffect;
		if (RespawnEffect != nullptr)
		{
			UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, RespawnEffect, WeaponMesh->GetComponentLocation());
		}
	}
}

/**
 * 武器可用性复制通知函数。
 */
void ALyraWeaponSpawner::OnRep_WeaponAvailability()
{
	if (bIsWeaponAvailable)
	{
		// 武器可用：播放重生特效并显示
		PlayRespawnEffects();
		SetWeaponPickupVisibility(true);
	}
	else
	{
		// 武器不可用：隐藏、开始冷却并播放拾取特效
		SetWeaponPickupVisibility(false);
		StartCoolDown();
		PlayPickupEffects();
	}	
}

/**
 * 获取生命周期复制属性。
 */
void ALyraWeaponSpawner::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	// 复制bIsWeaponAvailable属性
	DOREPLIFETIME(ALyraWeaponSpawner, bIsWeaponAvailable);
}

/**
 * 从物品定义中获取默认统计值。
 */
int32 ALyraWeaponSpawner::GetDefaultStatFromItemDef(const TSubclassOf<ULyraInventoryItemDefinition> WeaponItemClass, FGameplayTag StatTag)
{
	if (WeaponItemClass != nullptr)
	{
		// 获取物品定义的默认对象
		if (ULyraInventoryItemDefinition* WeaponItemCDO = WeaponItemClass->GetDefaultObject<ULyraInventoryItemDefinition>())
		{
			// 查找设置统计信息的片段
			if (const UInventoryFragment_SetStats* ItemStatsFragment = Cast<UInventoryFragment_SetStats>( WeaponItemCDO->FindFragmentByClass(UInventoryFragment_SetStats::StaticClass()) ))
			{
				// 返回指定标签的统计值
				return ItemStatsFragment->GetItemStatByTag(StatTag);
			}
		}
	}

	// 未找到返回0
	return 0;
}